import java.io.*;
import java.net.*;
import java.util.Scanner;
import java.util.concurrent.CopyOnWriteArrayList;

public class propertise {
    public static void main(String[] args) throws IOException {
        //创建服务器对象 以及接收端口
        ServerSocket ss = new ServerSocket(10088);
        //创建一个集合，用来存储服务器接收的客户
        CopyOnWriteArrayList<Socket> sslisk = new CopyOnWriteArrayList<Socket>();
        //此处死循环一直在接收客户端对象，然后开启新的线程让客户端对象进入，执行代码
        while (true) {
            System.out.println("服务器等待连接中。。。。。");
            //服务器等待客户端的连接
            Socket s = ss.accept();
            //将客户端增加到这个集合中
            sslisk.add(s);
            System.out.println(ss+"加入了群聊");
            //开启线程与服务端交互
            //开启任务
            ServerSocketruan run = new ServerSocketruan(s,sslisk);
            //绑定任务
            new Thread(run).start();
        }
    }
}
class ServerSocketruan implements Runnable {
    //两个成员变量  一个是接收到的客户端 另一个是客户端集合
    private Socket ss;
    private CopyOnWriteArrayList<Socket> sslisk;//此处记得加泛型

    public ServerSocketruan(Socket ss, CopyOnWriteArrayList sslisk) {
        this.ss = ss;
        this.sslisk = sslisk;
    }

    public Socket getSs() {
        return ss;
    }

    public void setSs(Socket ss) {
        this.ss = ss;
    }

    public void setSslisk(CopyOnWriteArrayList sslisk) {
        this.sslisk = sslisk;
    }

    public CopyOnWriteArrayList getSslisk() {
        return sslisk;
    }

    @Override
    public void run() {
        //死循环，一直读取客户端发送来的信息
        //读取到数据后遍历服务器集合
        //判断遍历到的是不是自己，是自己不用管，不是自己则获取输入流
        //当线程出现异常，说明客户端下线了，则从集合中去除
        try {
            //获取客户端的信息 并包装为数据流
            DataInputStream dainput = new DataInputStream(ss.getInputStream());
            //获取完信息开始死循环一直读取信息，不然只能读一次
            while (true) {
                //在此处开始读数据，如果成功了代码继续执行，如果读不出来，就证明出现异常，开始下线
                String s = dainput.readUTF();
                //开始遍历客户端集合，判断是否为当前客户端，不是当前客户端则把这条信息也发送给他们
                sslisk.forEach(kh -> {
                    //判断这个kehu是否为当前的连接的客户  不是结果为true进入循环
                    //此处ss为客户
                    if (!kh.equals(ss)) {
                        try {
                            OutputStream outputStream = kh.getOutputStream();
                            DataOutputStream dataOutputStream = new DataOutputStream(outputStream);
                            dataOutputStream.writeUTF(s);

                        } catch (IOException e) {
                            throw new RuntimeException(e);
                        }
                    }
                });
            }
        } catch (IOException e) {
            //throw new RuntimeException(e);
            //如果没有接收到客户的信息，就证明下线了
            System.out.println(ss+"下线了");
            sslisk.remove(ss);
        }
    }
}